package com.taoge.webrtc.netty;

import cn.hutool.core.collection.CollUtil;
import com.alibaba.fastjson.JSON;
import com.taoge.webrtc.constant.ChatConstant;
import com.taoge.webrtc.entity.ChatMsg;
import io.netty.channel.*;
import io.netty.handler.codec.http.websocketx.*;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;

import java.util.*;
import java.util.concurrent.ConcurrentHashMap;

//文本消息处理器
@Component
@ChannelHandler.Sharable
@Slf4j
public class TextSocketHandler extends SimpleChannelInboundHandler<TextWebSocketFrame> {

    //模拟用户所在的群聊
    private static final List<Integer> groupIds = new ArrayList<>();

    static {
        groupIds.add(1);
    }

    //用户id=>channel示例 可以通过用户的唯一标识保存用户的channel 这样就可以发送给指定的用户
    public static ConcurrentHashMap<String, Channel> singleChannel = new ConcurrentHashMap<>();
    //群id和用户id集合
    public static ConcurrentHashMap<String, Set<String>> groupChannel = new ConcurrentHashMap<>();

    @Override
    protected void channelRead0(ChannelHandlerContext ctx, TextWebSocketFrame msg) throws InterruptedException {
        //接收的消息
        String text = msg.text();
        ChatMsg chatMsg = JSON.parseObject(text, ChatMsg.class);
        Integer type = chatMsg.getType();
        //退出连接
        if (type.equals(ChatConstant.MSG_TYPE_LOGOUT)) {
            disConnect(chatMsg, ctx);
            //创建连接
        } else if (type.equals(ChatConstant.MSG_TYPE_LOGIN)) {
            createConnect(chatMsg, ctx);
            //聊天/提议/应答//候选
        } else if (type.equals(ChatConstant.MSG_TYPE_TEXT)
                || type.equals(ChatConstant.MSG_TYPE_OFFER)
                || type.equals(ChatConstant.MSG_TYPE_ANSWER)
                || type.equals(ChatConstant.MSG_TYPE_CANDIDATE)
                || type.equals(ChatConstant.MSG_TYPE_HANGUP)
        ) {
            log.info("收到客户端{}的数据：{})", ctx.channel().id(), text);
            //单聊
            if (chatMsg.getGroupId() == null) {
                sendSingleMsg(chatMsg);
                //群聊
            } else {
                sendGroupMsg(chatMsg);
            }
        }
    }

    //单聊
    private void sendSingleMsg(ChatMsg chatMsg) {
        String key = chatMsg.getTo().toString();
        if (singleChannel.containsKey(key)) {
            Channel channel = singleChannel.get(key);
            channel.writeAndFlush(new TextWebSocketFrame(JSON.toJSONString(chatMsg)));
        } else {
            //离线状态
            log.info("对方处于离线状态。。。");
        }
    }

    //群聊
    private void sendGroupMsg(ChatMsg chatMsg) {
        String key = chatMsg.getFrom().toString();
        Set<String> idSet = groupChannel.get(chatMsg.getGroupId().toString());
        if (CollUtil.isEmpty(idSet)) return;
        for (String id : idSet) {
            if (id.equals(key)) continue;
            Channel channel = singleChannel.get(id);
            channel.writeAndFlush(new TextWebSocketFrame(JSON.toJSONString(chatMsg)));
        }
    }

    //创建连接
    private void createConnect(ChatMsg chatMsg, ChannelHandlerContext ctx) {
        String key = chatMsg.getFrom().toString();
        Channel channel = ctx.channel();
        singleChannel.put(key, channel);
        for (Integer groupId : groupIds) {
            Set<String> idSet = groupChannel.get(groupId.toString());
            if (idSet == null) {
                idSet = new HashSet<>();
            }
            if (idSet.add(key)) {
                groupChannel.put(groupId.toString(), idSet);
            }
        }
        String id = channel.id().toString();
        log.info("连接{}加入！当前在线人数为{}", id, getOnlineCount());
    }

    //断开连接
    private void disConnect(ChatMsg chatMsg, ChannelHandlerContext ctx) throws InterruptedException {
        // 关闭连接
        ctx.channel().close().sync();
        //从单聊中移除
        String key = chatMsg.getFrom().toString();
        boolean one = singleChannel.remove(key) != null;
        if (!one) {
            //从群聊中移除
            for (Integer groupId : groupIds) {
                Set<String> idSet = groupChannel.get(groupId.toString());
                idSet.remove(key);
            }
            String id = ctx.channel().id().toString();
            log.info("连接{}断开！当前在线人数为{}", id, getOnlineCount());
        }
    }

    //服务端监听到客户端活动
    @Override
    public void channelActive(ChannelHandlerContext ctx) {

    }

    //服务端监听到客户端不活动
    @Override
    public void channelInactive(ChannelHandlerContext ctx) {

    }

    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) {
        ctx.close();
        log.error("netty服务器发生了异常:  {0} ", cause);
    }

    public static int getOnlineCount() {
        return singleChannel.size();
    }

}
